﻿#include <QMetaMethod>
#include <QJsonDocument>
#include <QJsonObject>
#include "JZWebServer.h"

JZWebServer::JZWebServer(QObject* parent)
    :QObject(parent)
{
    m_server = new QTcpServer(this);
    connect(m_server, &QTcpServer::newConnection, this, &JZWebServer::onNewConnection);
}

JZWebServer::~JZWebServer()
{
    stop();
}

bool JZWebServer::start(int port)
{
    return m_server->listen(QHostAddress::Any, port);
}

void JZWebServer::stop()
{
    m_server->close();
}

void JZWebServer::onNewConnection()
{
    //获取新连接
    QTcpSocket* socket = m_server->nextPendingConnection();
    if (!socket)
        return;

    m_requests[socket] = JZWebRequestPtr(new HttpRequest());
    connect(socket, &QTcpSocket::readyRead, this, &JZWebServer::onReadyRead);
    connect(socket, &QTcpSocket::disconnected, this, &JZWebServer::onDisConnection);
}

void JZWebServer::onDisConnection()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
    m_requests.remove(socket);
}

void JZWebServer::onReadyRead()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
    
    auto currentRequest = m_requests[socket].data();
    bool complete = true;
    do
    {
        // Collect data for the request object
        while (socket->bytesAvailable() &&
            currentRequest->getStatus() != HttpRequest::complete &&
            currentRequest->getStatus() != HttpRequest::abort_size &&
            currentRequest->getStatus() != HttpRequest::abort_broken)
        {
            currentRequest->readFromSocket(socket);
        }

        int status = currentRequest->getStatus();
        // If the request is aborted, return error message and close the connection
        if (currentRequest->getStatus() == HttpRequest::abort_size)
        {
            socket->write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
            break;
        }
        // another reson to abort the request
        else if (currentRequest->getStatus() == HttpRequest::abort_broken)
        {
            socket->write("HTTP/1.1 400 bad request\r\nConnection: close\r\n\r\n400 Bad request\r\n");
            break;
        }
        // If the request is complete, let the request mapper dispatch it
        else if (currentRequest->getStatus() == HttpRequest::complete)
        {
            HttpResponse response;
            emit sigHttpRequest(*currentRequest, response);
            response.write(QByteArray(), true);
            socket->write(response.data());
            break;
        }
        complete = false;
    } while (0);    
    
    if (complete)
        socket->close();
}